#ifndef EPOLL_SERVER_H
#define EPOLL_SERVER_H

#include <sys/epoll.h>
#include "definition.h"

#define MAX_BUFF_POOL 131072
#define MAXSOCKFD 9999
#define MAX_EVENTS 1024

/* event dispatch */
#ifdef DISPATCH
typedef struct event_queue_item {
	struct event_queue_item *next;
	struct epoll_event event;
} eq_item;

#ifdef MEMPOOL
typedef struct mem_pool
{
	u_char *startptr;      /* start pointer */
	eq_item *freeptr;   /* pointer to the start memory chunk */
	int free_chunks;       /* number of total free chunks */
	int total_chunks;       /* number of total free chunks */
	int chunk_size;        /* chunk size in bytes */
	pthread_mutex_t lock;
} mem_pool;
#endif

typedef struct events_queue {
	struct event_queue_item *head;
	struct event_queue_item *tail;
	pthread_mutex_t lock;
	mem_pool *event_pool;
} events_queue;
#endif

typedef struct thread_contex {
	pthread_t thread_id;	/* unique ID of this thread */
#ifdef DISPATCH
	int notify_receive_fd;	/* receiving end of notify pipe */
	int notify_send_fd;	/* sending end of notify pipe */
	struct events_queue *new_events_queue;
#ifdef COND_SIG
	pthread_mutex_t lock;
	pthread_cond_t cond;
#endif
#endif
#ifdef BACKUP_LEADER
	int backupfd[2]; //
#endif
	uint32_t num_msg;
	int efd; /* unique epoll id for this thread */
} thread_contex;

/* ring buffer */
typedef struct RingBuffer {
    char pool[MAX_BUFF_POOL];
    int head; // head: always points to an empty bit
    int tail; // tail: only head == tail that tail refers to an empty bit
    int process; // where the processData stops, the bit NOT processed
    int headremain; // the free space after head
    int totalremain; // the total free space overall ring
} RingBuffer;

typedef struct LeonRing {
	RingBuffer *sockfd[MAXSOCKFD];
	int maxsockfd;
} LeonRing;

int initRingBuffer(RingBuffer *ringbuf);
int tidyRing(RingBuffer *ringbuf); // mv data to start point
int pushRing(RingBuffer *ringbuf, char *databuf, int lendata);
int recvRing(RingBuffer *ringbuf, int sockfd); // return read's returned value
int lenRingSend(RingBuffer *ringbuf);

int initLeonRing(LeonRing *leon);
int freeLeonRing(LeonRing *leon);
int checkLeonRing(LeonRing *leon, int sockfd);

int recvLeonRing(LeonRing *leon, int sockfd);
int processLeonRing(LeonRing *leon, int sockfd, uint32_t *num_msg, struct thread_contex *me);
int processData(char *databuf, int lendata, uint32_t *num_msg); // return data processed


#endif // RINGBUFF_H
